; *******************************
; Netflix Silverlight Control v0.9
; *******************************
;
; AutoHotKey script for control of Netflix: Movie Viewer in Internet Explorer
; TODO refind buttons on window location change or use relative positions
; TODO consider searching only in active window for buttons and then calculation absolute position
; TODO hotkey to move window to different monitor
; TODO only find buttons on resize of window


; Initialize window group
ViewerWindowTitle := "Netflix"
MPCWindowTitle := "ahk_class MediaPlayerClassicW"
FullScreenWindowTitle := "ahk_class AGFullScreenWinClass"

GroupAdd, ViewerWindow, %ViewerWindowTitle%
GroupAdd, ViewerWindow, %MPCWindowTitle%

;SetTitleMatchMode 2
DetectHiddenWindows On

if WinExist("NetflixSilverlightControl")
{
    WinClose, NetflixSilverlightControl
    WinWaitClose, NetflixSilverlightControl
}


if WinExist(A_ScriptFullPath)
{
    ; Window exists... do nothing.
    WinSetTitle, NetflixSilverlightControl
}
else
{
    ; The actual control script isn't running.  Run it.
    ;Run, %nscExe%
}
DetectHiddenWindows Off

#Persistent
#NoEnv
#SingleInstance force

; Init onmessage

OnMessage(0x5555, "HandleMessage")

HandleMessage(wParam, lParam, msg)
{


    if (wParam = 10)
    {

        ; Decide the action to take
        ; (AHK has no switch/case so, we'll have to use else if)
        if (lParam = 100)
        {
            Gosub, CloseViewer ; Exit the netflix movie viewer, restart this script, and wait for a new viewer window to open
        }
        else if (lParam = 101)
        {
            Gosub, JumpAhead
        }
        else if (lParam = 102)
        {
            TrayTip, netfix, jump forward
            Gosub, JumpBack ; Jump back in the timeline
        }
        else if (lParam = 103)
        {
            Gosub, NextEpisode ; Move to next Chapter/Episode
        }
        else if (lParam = 104)
        {
            Gosub, PrevEpisode ; Move to previous Chapter/Episode
        }
        else if (lParam = 105)
        {
            Gosub, Play ; Play
        }
        else if (lParam = 106)
        {
            Gosub, Pause ; Pause
        }
        else if (lParam = 107)
        {
            Gosub, TogglePause ;Toggle play/pause
        }
        else if (lParam = 108)
        {
            Gosub, ToggleMute ; Toggle Mute On/Off
        }
        else if (lParam = 109)
        {
            Gosub, VolumeUp ; Move volume Up 
        }
        else if (lParam = 110)
        {
            Gosub, VolumeDown ; Move volume down
        }
        else if(lParam = 111)
        {
            Gosub, EnterFullScreen ; enter full screen
        }
        else if(lParam = 112)
        {
            Gosub, ExitFullScreen ; exit fullscreen
        }
        else if(lParam = 113)
        {
            Gosub, EnterFullScreen ; enter full screen
            ; NEED TO WAIT UNTIL IT STARTS AND PAUSE IT
        }

    }

    ; Since returning quickly is often important, it is better to use a ToolTip than
    ; something like MsgBox that would prevent the function from finishing:
    ;TrayTip, Netfix, Message %msg% arrived:`nWPARAM: %wParam%`nLPARAM: %lParam%
    ;MsgBox,  Message %msg% arrived:`nWPARAM: %wParam%`nLPARAM: %lParam%
}


; Start of script main loop.
; ***************************
ScriptStart:

; initialize variables
ScriptMode := 0
TimePosition := 0
TimeMovementBuffer := 0
TimeMovementCount := 0
TimeMovementMode := 0

Gosub, NotifyClose

; screensaver stuff
ES_CONTINUOUS := 0x80000000
ES_DISPLAY_REQUIRED := 0x00000002
windowsState := 0 ; 0 - netflix not running, 1 - netflix running but not active, 2 - netflix running but not fullscreen, 3 - netflix is fullscreen
sleepDelay := 150 ; mins
Menu, Tray, Icon, SHELL32.dll, 44
OnExit, ExitSub


; Wait for a Netflix Movie Viewer window to open
WinWait, ahk_group ViewerWindow


; Set timer to check if window closes
SetTimer, CheckViewerWindow, 500

; Buffer events
#MaxThreadsBuffer On

Gosub, NotifyOpen

return

; **********************************
; Netflix Viewer Control Subroutines
; **********************************
;
; Call with "Gosub, <name>"
; Example:
; Gosub, VolumeUp
;


; Exit the netflix movie viewer, and wait
; for a new viewer window to open
; ******************************************
CloseViewer:
;TrayTip, NetFix, CloseViewer
    ScriptMode := 0
    SetTimer, CheckViewerWindow, Off
    SetTimer, DoTimeScroll, Off
    IfWinExist, ahk_group ViewerWindow
        WinClose, ahk_group ViewerWindow
        WinWaitClose, ahk_group ViewerWindow
    Gosub, NotifyClose
    Reload

return

; Jump ahead about 10 pixels in the timeline
; ******************************************
JumpAhead:
TrayTip, NetFlix, %FarRightTime%
    if (ScriptMode < 1)
    {
        TrayTip, test, scriptmode < 1
        return
    }
    TimeMovementBuffer += 1
    SetTimer, DoTimeScroll, 100

return

; Jump back about 10 pixels in the timeline
; ******************************************
JumpBack:

    if (ScriptMode < 1)
        return
    TimeMovementBuffer -= 8
    SetTimer, DoTimeScroll, 100

return

; Move to next Chapter/Episode
; *****************************
NextEpisode:

    if (ScriptMode < 1)
        return
    if (NextChapter > 0)
    {
        ;CoordMode Mouse
        result := WaitForBar()
        Gosub, ExitFullScreen
        ; Wait for the chapter button to become visible
        result := GetButtonPos("nf_next_chap.bmp", 15, 11, 100, 0)
        result := ClickPos(NextChapter)
        ; Wait 2 seconds for the new video to load
        sleep 2000
        ; enter back into full screen
        result := GetButtonPos("nf_fs.bmp", 59, 16, 200, 0)
        PreviousChapter := GetButtonPos("nf_prev_chap.bmp", 15, 11, 1, 0)
	NextChapter := GetButtonPos("nf_next_chap.bmp", 15, 11, 1, 0)
        Gosub, EnterFullScreen
    }

return

; Move to previous Chapter/Episode
; *********************************
PrevEpisode:

    if (ScriptMode < 1)
        return
    if (PreviousChapter > 0)
    {
        ;CoordMode Mouse
        result := WaitForBar()
        Gosub, ExitFullScreen
        ; Wait for the chapter button to become visible
        result := GetButtonPos("nf_prev_chap.bmp", 15, 11, 100, 0)
        result := ClickPos(PreviousChapter)
        ; Wait 2 seconds for the new video to load
        sleep 2000
        ; enter back into full screen
        result := GetButtonPos("nf_fs.bmp", 59, 16, 200, 0)
        PreviousChapter := GetButtonPos("nf_prev_chap.bmp", 15, 11, 1, 0)
	NextChapter := GetButtonPos("nf_next_chap.bmp", 15, 11, 1, 0)
        Gosub, EnterFullScreen
    }

return

; Play
; *****************************
Play:

    if (ScriptMode < 1)
        return
    ;CoordMode Mouse
    result := WaitForBar()
    Play := GetButtonPos("nf_play.bmp", 57, 21, 1, 0)
    if (Play > 0)
    {
        result := ClickPos(Play)
    }

return

; Pause
; *****************************
Pause:

    if (ScriptMode < 1)
        return
    ;CoordMode Mouse
    result := WaitForBar()
    Button := GetButtonPos("nf_pause_a.bmp", 57, 21, 1, 45)
        if (Button > 0)
        {
            result := ClickPos(Button)
            return
        }
    Button := GetButtonPos("nf_pause_b.bmp", 57, 21, 1, 45)
        if (Button > 0)
        {
            result := ClickPos(Button)
            return
        }
return

; Toggle play/pause
; *****************************
TogglePause:

    if (ScriptMode < 1)
        return
    ;CoordMode Mouse
    result := WaitForBar()
    result := ClickPos(Pause)

return

; Toggle Mute On/Off
; *****************************
ToggleMute:

    if (ScriptMode < 1)
        return
    ;CoordMode Mouse
    result := WaitForBar()
    result := ClickPos(Vol)

return

; Move volume Up
; *****************************
VolumeUp:

    if (ScriptMode < 1)
        return

    VolPos := GetVolumeBarPos(Vol)

    ;CoordMode Mouse
    if (VolPos > 0)
    {
        x := GetX(Vol)
        NewVolPos := (VolPos - 5)
        MouseMove, %x%, %VolPos%, 5
        MouseClickDrag, Left, x, VolPos, x, NewVolPos, 5
    }

return

; Move volume down
; *****************************
VolumeDown:

    if (ScriptMode < 1)
        return

    VolPos := GetVolumeBarPos(Vol)

    ;CoordMode Mouse
    if (VolPos > 0)
    {
        x := GetX(Vol)
        NewVolPos := (VolPos + 5)
        MouseMove, %x%, %VolPos%, 3
        MouseClickDrag, Left, x, VolPos, x, NewVolPos, 3
    }

return

; Toggle full screen
; ***************************

EnterFullScreen:
    WinGetPos, x, y, width, height, A
    SysGet, Mon, Monitor, 2
    
    ;MsgBox, Left: %MonLeft% -- Top: %MonTop% -- x: %x% -- width: %width%
    if (x + (width / 2) < MonLeft) {
        SetWinDelay, 0
        WinMove,A,,MonLeft + 1 - (width / 2),MonTop, MonRight - MonLeft, MonBottom - MonTop
    }
    ControlFocus, NativeWindowClass1, %ViewerWindowTitle%
    ControlSend, NativeWindowClass1, fff, %ViewerWindowTitle%
    ControlFocus, NativeWindowClass1, %ViewerWindowTitle%
return

ExitFullScreen:
    SendInput, {Esc}
    ; ClickPos(ExitFullScreen)
return


FindEnterFullScreen:
    EnterFullScreen := GetButtonPos("nf_fs.bmp", 59, 16, 400, 0)
    ;TrayTip, NetFix, EnterFullScreen - %EnterFullScreen%
    if(EnterFullScreen > 0) {
    
        NfsBarPos := (GetY(EnterFullScreen) - 20)

        ; If this a a TV series, there could be chapter buttons.  Find them
        PreviousChapter := GetButtonPos("nf_prev_chap.bmp", 15, 11, 1, NfsBarPos)
        NextChapter := GetButtonPos("nf_next_chap.bmp", 15, 11, 1, NfsBarPos)
        ;result := HideMouse()
        ;ExitFullScreen := 0
    } else { ; we couldn't find enter full screen, do we really know where exit full screen is?
        ; TODO What should we really do?
        ExitFullScreen := 0
    }
return

FindExitFullScreen:
    ScriptMode := 0
    ;TrayTip, Winfix, Looking...
    ; Now that we are in full screen, find the "Exit Full Screen" button
    ; This will let us know that we are in full screen mode
    ; Wait about 10 seconds for the full screen button (100 loops of up to 100ms each)
    Loop, 100
    {
        result =: WiggleMouse()
        ExitFullScreen := GetButtonPos("nf_efs.bmp", 57, 21, 1, 45)
            if (ExitFullScreen > 0)
                break
        Sleep, 100
    }
    ;TrayTip, Winfix, ExitFullScreen is %ExitFullScreen%
    ;if(ExitFullScreen > 0) {
    ;    TrayTip, NetFix, ExitFullScreen - %ExitFullScreen%
    ;}
    ; now find the pause button
    Loop, 100
    {
        result =: WiggleMouse()
        Pause := GetButtonPos("nf_pause_a.bmp", 57, 21, 1, 45)
            if (Pause > 0)
               break
        Pause := GetButtonPos("nf_pause_b.bmp", 57, 21, 1, 45)
            if (Pause > 0)
                break
        Sleep, 100
    }

;    Loop, 100
;    {
;        result =: WiggleMouse()
;        Play := GetButtonPos("nf_play.bmp", 57, 21, 1, 45)
;            if (Play > 0)
;               break
;        Sleep, 100
;    }
;    if(Play > 0)
;        TrayTip, netfix, Play = %Play%

    ; and now look for the volume button in all its various forms
    Loop, 50
    {
        result =: WiggleMouse()
        Vol := GetButtonPos("nf_vol_a.bmp", 20, 20, 1, 45)
            if (Vol > 0)
               break
        Vol := GetButtonPos("nf_vol_b.bmp", 20, 20, 1, 45)
            if (Vol > 0)
                break
        Vol := GetButtonPos("nf_vol_c.bmp", 20, 20, 1, 45)
            if (Vol > 0)
                break
        Sleep, 100
    }
    if(Vol > 0) {
        TrayTip, netfix, Vol = %Vol%
    }

    ; Estimate the width of the timeline bar for later use in jumping forward/back
    ; We base it off the position of the pause and exit full screen buttons
    FarLeftTime := (GetX(Pause) + 56)
    TimeLine := (GetY(Pause) - 6)
    FarRightTime := (GetX(ExitFullScreen) - 98)

    ; Let the hot key events know that we have everything set up, and they can now run
    ScriptMode := 1
return


; *******************
; Timer Subroutines
; *******************

; Used by check viewer window timer
; Perodically check if the viewer window is open
; If not, re-start from the top
CheckViewerWindow:
; windowsState values
; 0 - netflix is not running
; 1 - netflix is running, but not active
; 2 - netflix window is active
; 3 - fullscreen is active

    IfWinNotExist, ahk_group ViewerWindow
    { ;netflix is not running
        SetTimer, ScreenSaveActivate, -1 ; run sub and turn off the timer (and reset windowsState to 0)
        TrayTip, NetFix, WinNotExist
        ScriptMode := 0
        SetTimer, CheckViewerWindow, Off
        SetTimer, DoTimeScroll, Off
        ;Goto, ScriptStart
        Reload
    }
    DetectHiddenWindows, Off
    oldWindowsState := windowsState
    mpcExist := WinExist(MPCWindowTitle)
    netflixExist := WinExist(ViewerWindowTitle)
    fullscreenExist := WinExist(FullScreenWindowTitle)
    If (windowsState != 2 && (netflixExist || mpcExist) && !fullscreenExist)
    { ; netflix exists but not fullscreen
        TrayTip, netfix, netflix exists not fullscreen
       windowsState := 2
       ScriptMode := 0
    } else if ( windowsState != 3 && fullscreenExist)
    { ; netflix exists and fullscreen
        TrayTip, netfix, netflix fullscreen
        windowsState := 3
    } else if (windowsState != 1 && !(netflixExist || mpcExist) && !fullscreenExist) {
        ; the window exists, but is not fullscreen
        TrayTip, netfix, netflix not exist
        ScriptMode := 0
        windowsState := 1
    }
    if (oldWindowsState <= 1 && windowsState > 1) {
        Menu, Tray, Icon, user32.dll, 2
        ;TrayTip, Netfix, Screen Saver Disabled`, Enjoy The Show! (windowsState = %windowsState%`, oldWindowsState = %oldWindowsState%, 10, 2
        DllCall("SystemParametersInfo", Int,17, Int,0, UInt,NULL, Int,2) ;disable screensaver
        DllCall("SetThreadExecutionState", UInt, ES_CONTINUOUS + ES_DISPLAY_REQUIRED) ;prevent sleep
        SetTimer, NetflixTimeOut, % -sleepDelay * 60*1000 ;run only once
    } else if(oldWindowsState > 1 && windowsState <= 1) { 
        SetTimer, ScreenSaveActivate, -1 ; run sub and turn off the timer
    }
    if(oldWindowsState < 3 && windowsState = 3) {
        ; Full Screen activated...
    }
    
return


; Used by jump ahead/back hotkeys
DoTimeScroll:

    if ((TimeMovementBuffer = 0)
    | ((((TimePosition + TimeMovementBuffer) > FarRightTime)  | ((TimePosition + TimeMovementBuffer) < FarLeftTime)) & (TimeMovementMode = 1)))
        {
            TimePosition += TimeMovementBuffer
            TimeMovementBuffer := 0
            if (TimePosition > FarRightTime)
            {
                TimePosition := (FarRightTime)
            }
            if (TimePosition < FarLeftTime)
            {
                TimePosition := (FarLeftTime)
            }
            ; Hiding the mouse, and then repositioning it
            ; keeps the navigation bar active while waiting for
            ; the movment timer to time out
            result := HideMouse()
            ;CoordMode Mouse
            MouseMove, %TimePosition%, %TimeLine%, 0
            TimeMovementCount += 1
            if (TimeMovementCount > 10)
            {
                ;CoordMode Mouse
                MouseMove, %TimePosition%, %TimeLine%, 0
                result := WaitForBar()
                ;CoordMode Mouse
                
                Click, %TimePosition%, %TimeLine%
                TimeMovementMode := 0
                SetTimer,DoTimeScroll,Off
                result := HideMouse()
            }
        }
        else
        {
            TimeMovementCount  := 0
            if (TimeMovementMode = 0)
            {
                TimeMovementMode := 1
                result := WaitForBar()
                CurPos := GetButtonPos("nf_mark.bmp", 2, 10, 1, 45)
                TimePosition := GetX(CurPos)
            }
            TimePosition += TimeMovementBuffer
            TimeMovementBuffer := 0
            if (TimePosition > FarRightTime)
            {
                TimePosition := (FarRightTime)
            }
            if (TimePosition < FarLeftTime)
            {
                TimePosition := (FarLeftTime)
            }
            ;CoordMode Mouse
            MouseMove, %TimePosition%, %TimeLine% , 0 
    }
   
return

; *************************
; Used to notify EventGhost
; *************************

NotifyClose:

    SetTitleMatchMode 1
    DetectHiddenWindows On
  
    ifWinExist, EventGhost ahk_class HiddenMessageReceiver
    {
        WinGet, pID, PID
        EventGhostPath := GetModuleFileNameEx(pID)
        Run, %EventGhostPath% -e NetflixSilverlightControl.PlayerClose
    }

return


NotifyOpen:

    SetTitleMatchMode 1
    DetectHiddenWindows On
  
    ifWinExist, EventGhost ahk_class HiddenMessageReceiver
    {
        WinGet, pID, PID
        EventGhostPath := GetModuleFileNameEx(pID)
        Run, %EventGhostPath% -e NetflixSilverlightControl.PlayerOpen
    }

return


; Screen Saver Stuff
ScreenSaveActivate:
Menu, Tray, Icon, SHELL32.dll, 44
TrayTip, Netfix, Screen Saver Enabled!, 10, 1
DllCall("SystemParametersInfo", Int,17, Int,1, UInt,NULL, Int,2) ;enable screensaver
DllCall("SetThreadExecutionState", UInt, ES_CONTINUOUS) ;enable sleep
SoundSet,100
SetTimer, NetflixTimeOut, OFF
windowsState := 0
Return

NetflixTimeOut:
MsgBox, Zzzzzzzz...
Return

ExitSub:
Gosub, ScreenSaveActivate
ExitApp


; ****************************
; Functions
; ****************************


; Look for position on an image
GetButtonPos(g_image,g_width,g_height,g_wait,y_start)
{
    full_image_path := A_ScriptDir . "\netflix_player_buttons\" . g_image
    reslt = 0
    ; these got the full desktop size
    ;SysGet, VirtualWidth, 78
    ;SysGet, VirtualHeight, 79
    ; this gets active window width and height
	WinGetPos, ,,VirtualWidth, VirtualHeight, A

    ;CoordMode Pixel
    Loop, %g_wait%
    {
        ;TrayTip, GetButtonPos, %g_image% - %g_wait%
        ImageSearch, FoundX, FoundY, 0, %y_start%, VirtualWidth, VirtualHeight, %full_image_path%
        if ErrorLevel = 0
        {
             ; Pack X,Y coords as two 16 bit integers in one 32 bit word.
             ; We do this because autohotkey does not yet support arrays,
             ; and we can only return one value from this function
             ;MsgBox, ,Test, %g_image% found at %FoundX%`, %Foundy% out of %VirtualWidth%x%VirtualHeight% with y-start=%y_start%
             x := (FoundX + (g_width/2))
             y := ((Foundy + (g_height/2)) << 16)
             reslt := (y | x)
             break
        }
        else
        {
            if (g_wait > 1)
                Sleep, 100
        }
    }
    return reslt
}


; Move to position
MoveToPos(position)
{
    x := (position & 65535)
    y := (position >> 16)
    ;CoordMode Mouse
    MouseMove, %x%, %y%, 0
    return 0
}


; Move mouse to lower right corner of screen
HideMouse()
{
    ;CoordMode Mouse
    MouseMove, %A_ScreenWidth%, %A_ScreenHeight%, 0
    return 0
}


; Click a position, them move the mouse to the lower right
; corner of the screen 
ClickPos(position){
    x := (position & 65535)
    y := (position >> 16)
    ;CoordMode Mouse
    MouseMove, %x%, %y%, 0
    MouseMove, %x%, %y%, 1
    ;CoordMode Mouse
    Click, %x%, %y%
    result := HideMouse()
    return 0
}


; Get the "X" portion of a position
GetX(position)
{
    x := (position & 65535)
    y := (position >> 16)
    return x
}


; Get the "Y" portion of a position
GetY(position)
{
    x := (position & 65535)
    y := (position >> 16)
    return y
}


; Move the mouse cursor around a bit in order to bring up
; the netflix navigation bar that auto hides
WiggleMouse()
{
    wiggle := (A_ScreenWidth - 10)
    ;CoordMode Mouse
    MouseMove, %A_ScreenWidth%, %A_ScreenHeight%, 2
    ;CoordMode Mouse
    MouseMove, %wiggle%, %A_ScreenHeight%, 2 
    ;CoordMode Mouse
    MouseMove, %A_ScreenWidth%, %A_ScreenHeight%, 2
    ;CoordMode Mouse
    ;MouseMove, %wiggle%, %A_ScreenHeight%, 1 
    return 0
}


; See of the netflix navigation bar is visible
; and bring it up, if not
WaitForBar()
{
    result := LookForVolumeButton()
    if (result = 0)
    {
  
        result := WiggleMouse()

        Loop, 50
        {
            result := LookForVolumeButton()
            if (result = 1)
                break
            Sleep, 50       
        } 
        return result
    }
    return result
}


; See of the volume button is visible
; (if it is, we know the navigation bar is visible)
LookForVolumeButton()
{

   full_image_path_a := A_ScriptDir . "\netflix_player_buttons\nf_vol_a.bmp"
   full_image_path_b := A_ScriptDir . "\netflix_player_buttons\nf_vol_b.bmp"
   full_image_path_c := A_ScriptDir . "\netflix_player_buttons\nf_vol_c.bmp"

   y_start := (A_ScreenHeight - 50)

       ;CoordMode Pixel
       ImageSearch, FoundX, FoundY, 0, %y_start%, A_ScreenWidth, A_ScreenHeight, %full_image_path_a%
           if ErrorLevel = 0
               return 1
       ImageSearch, FoundX, FoundY, 0, %y_start%, A_ScreenWidth, A_ScreenHeight, %full_image_path_b%
           if ErrorLevel = 0
               return 1
       ImageSearch, FoundX, FoundY, 0, %y_start%, A_ScreenWidth, A_ScreenHeight, %full_image_path_c%
           if ErrorLevel = 0
               return 1
    return 0

}


; Check if the volume slider bar is visible and return its position
; If its not visible, then make it visible
GetVolumeBarPos(Vol){
    result := LookForVolumeButton()
    if (result = 0)
    {
        result := WaitForBar()
    }

    VolPos := FindVolumeBar(Vol)
    if (VolPos = 0)
    {
        ; Look for volume bar
        result := MoveToPos(Vol)
        Loop, 20
        {
            VolPos := FindVolumeBar(Vol)
            if (VolPos > 0)
                break
            Sleep, 100
        }
    }
    return VolPos
}


; Return the position of the volume slider bar.  
; If its not visible return 0
FindVolumeBar(Vol){

    x := GetX(Vol)
    y := GetY(Vol)
    x1 := (x - 12)
    x2 := (x + 12)
    y1 := (y - 74)
    y2 := (y - 16)
    full_image_path_a := A_ScriptDir . "\netflix_player_buttons\nf_vol_slide_a.bmp"
    full_image_path_b := A_ScriptDir . "\netflix_player_buttons\nf_vol_slide_b.bmp"
    full_image_path_c := A_ScriptDir . "\netflix_player_buttons\nf_vol_slide_c.bmp"
    full_image_path_d := A_ScriptDir . "\netflix_player_buttons\nf_vol_slide_d.bmp"
    full_image_path_e := A_ScriptDir . "\netflix_player_buttons\nf_vol_slide_e.bmp"

    VolPos := 0

        ;CoordMode Pixel
        ImageSearch, FoundX, FoundY, %x1%, %y1%, %x2%, %y2%, %full_image_path_a%
        if ErrorLevel = 0
        {
            VolPos := (FoundY + 1)
            return VolPos
        }
        ImageSearch, FoundX, FoundY, %x1%, %y1%, %x2%, %y2%, %full_image_path_b%
        if ErrorLevel = 0
        {
            VolPos := (FoundY + 1)
            return VolPos
        }
        ImageSearch, FoundX, FoundY, %x1%, %y1%, %x2%, %y2%, %full_image_path_c%
        if ErrorLevel = 0
        {
            VolPos := (FoundY + 1)
            return VolPos
        }
        ImageSearch, FoundX, FoundY, %x1%, %y1%, %x2%, %y2%, %full_image_path_d%
        if ErrorLevel = 0
        {
            VolPos := (FoundY + 1)
            return VolPos
        }
        ImageSearch, FoundX, FoundY, %x1%, %y1%, %x2%, %y2%, %full_image_path_e%
        if ErrorLevel = 0
        {
            VolPos := (FoundY + 1)
            return VolPos
        }

    return VolPos
}



GetModuleFileNameEx( p_pid )
{
   if A_OSVersion in WIN_95,WIN_98,WIN_ME
   {
      MsgBox, This Windows version (%A_OSVersion%) is not supported.
      return
   }

   h_process := DllCall( "OpenProcess", "uint", 0x10|0x400, "int", false, "uint", p_pid )
   if ( ErrorLevel or h_process = 0 )
      return
   
   name_size = 255
   VarSetCapacity( name, name_size )
   
   result := DllCall( "psapi.dll\GetModuleFileNameExA", "uint", h_process, "uint", 0, "str", name, "uint", name_size )
   
   DllCall( "CloseHandle", h_process )
   
   return, name
} 
